package sf.dsl;

import sf.common.exception.SmallOrmException;
import sf.core.DBField;
import sf.core.DBObject;
import sf.database.dialect.DBDialect;
import sf.database.meta.ColumnMapping;
import sf.database.meta.MetaHolder;
import sf.database.meta.TableMapping;
import sf.database.util.SimpleSQLTemplate;
import sf.spring.util.CollectionUtils;
import sf.tools.StringUtils;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 通用的Example查询对象
 */
public class Example {

    protected boolean distinct;

    protected boolean count;

    protected boolean exists;

    protected boolean notNull;

    protected boolean forUpdate;

    /**
     * 使用java SQL定义的类型,该属性设置为true,则执行SQL时会跳过ColumnMapping和TypeHandler中的设值.
     * 此处主要是解决使用自定义类型转换时:如ObjectJacksonMapping,导致查询条件不好写的问题.
     */
    protected boolean useBasicType;

    /**
     * where 条件是否是使用了包装
     */
    protected boolean whereWrapper;

    /**
     * 表别名(只对查询生效)
     */
    protected String alias;

    //查询字段
    protected Set<DBField> selectColumns;

    //排除的查询字段
    protected Set<DBField> excludeColumns;

    protected DBField countColumn;

    /**
     * select字段权限最高,不为空,则不再判断selectColumns,excludeColumns,countColumn
     */
    protected String select;

    /**
     * 追加from字段
     */
    protected String from;

    protected List<Criteria> criterias;

    /**
     * 排序字段
     */
    protected Map<DBField, Order> orderMap;

    protected List<DBField> groupByList;

    protected Criterion having;

    /**
     * 查询总数限制
     */
    protected OffsetLimit offsetLimit;

    protected Class<?> entityClass;

    protected TableMapping table;
    //属性和列对应
    protected Map<DBField, ColumnMapping> propertyMap;
    //动态表名
    protected String tableName;

    protected DBDialect dialect;

    /**
     * 默认exists为true
     * @param entityClass
     */
    public Example(Class<? extends DBObject> entityClass) {
        this(entityClass, true);
    }

    /**
     * 带exists参数的构造方法，默认notNull为false，允许为空
     * @param entityClass
     * @param exists      - true时，如果字段不存在就抛出异常，false时，如果不存在就不使用该字段的条件
     */
    public Example(Class<? extends DBObject> entityClass, boolean exists) {
        this(entityClass, exists, false);
    }

    /**
     * 带exists参数的构造方法
     * @param entityClass
     * @param exists      - true时，如果字段不存在就抛出异常，false时，如果不存在就不使用该字段的条件
     * @param notNull     - true时，如果值为空，就会抛出异常，false时，如果为空就不使用该字段的条件
     */
    public Example(Class<? extends DBObject> entityClass, boolean exists, boolean notNull) {
        this.exists = exists;
        this.notNull = notNull;
        criterias = new ArrayList<Criteria>();
        orderMap = new LinkedHashMap<>(4);
        groupByList = new ArrayList<>(4);
        this.entityClass = entityClass;
        table = MetaHolder.getMeta(entityClass);
        propertyMap = table.getSchemaMap();
    }

    /**
     * 分页参数
     * @param start
     * @param limit
     * @return
     */
    public Example offsetLimit(long start, int limit) {
        this.offsetLimit = new OffsetLimit(start, limit);
        return this;
    }

    public Example groupBy(DBField... properties) {
        Collections.addAll(this.groupByList, properties);
        return this;
    }

    public String getGroupByClause(boolean useAlias) {
        StringBuilder sb = new StringBuilder();
        for (DBField field : groupByList) {
            if (propertyMap.containsKey(field)) {
                String name = propertyMap.get(field).getRawColumnName();
                if (StringUtils.isNotBlank(name)) {
                    if (dialect != null) {
                        name = dialect.wrapKeyword(name);
                    }
                    sb.append(sb.length() > 0 ? "," : "").append(getColumnAlias(name, useAlias));
                }
            }
        }
        return sb.toString();
    }

    public Example having(String condition, Collection<?> values) {
        having = new Criterion(" having " + condition, values);
        return this;
    }

    public Example orderBy(DBField property, Order order) {
        this.orderMap.put(property, order);
        return this;
    }

    public Example orderBy(DBField... properties) {
        return orderByAsc(properties);
    }

    public Example orderByAsc(DBField... properties) {
        for (DBField field : properties) {
            this.orderMap.put(field, Order.ASC);
        }
        return this;
    }

    public Example orderByDesc(DBField... properties) {
        for (DBField field : properties) {
            this.orderMap.put(field, Order.DESC);
        }
        return this;
    }

    public String getOrderByClause(boolean useAlias) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<DBField, Order> entry : orderMap.entrySet()) {
            DBField field = entry.getKey();
            if (propertyMap.containsKey(field)) {
                String name = propertyMap.get(field).getRawColumnName();
                if (StringUtils.isNotBlank(name)) {
                    if (dialect != null) {
                        name = dialect.wrapKeyword(name);
                    }
                    sb.append(sb.length() > 0 ? "," : "").append(getColumnAlias(name, useAlias)).append(" ")
                            .append(entry.getValue().name());
                }
            }
        }
        return sb.toString();
    }

    /**
     * 设置表别名
     * @param alias
     * @return
     */
    public Example alias(String alias) {
        this.alias = alias;
        return this;
    }


    /**
     * 设置表名
     * @param tableName
     */
    public Example tableName(String tableName) {
        this.tableName = tableName;
        return this;
    }

    public Example select(String select) {
        this.select = select;
        return this;
    }

    public Example from(String from) {
        this.from = from;
        return this;
    }

    /**
     * 排除查询字段，优先级低于 selectProperties
     * @param properties 属性名的可变参数
     * @return
     */
    public Example excludeProperties(DBField... properties) {
        if (properties != null && properties.length > 0) {
            if (this.excludeColumns == null) {
                this.excludeColumns = new LinkedHashSet<DBField>();
            }
            for (int i = 0; i < properties.length; i++) {
                DBField property = properties[i];
                if (propertyMap.containsKey(property)) {
                    this.excludeColumns.add(property);
                } else {
                    throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
                }
            }
        }
        return this;
    }

    public Example excludeProperties(Collection<DBField> properties) {
        if (properties != null && !properties.isEmpty()) {
            if (this.excludeColumns == null) {
                this.excludeColumns = new LinkedHashSet<DBField>();
            }
            for (DBField property : properties) {
                if (propertyMap.containsKey(property)) {
                    this.excludeColumns.add(property);
                } else {
                    throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
                }
            }
        }
        return this;
    }

    /**
     * 原始列名
     * @param field
     * @return
     */
    public String rawColumnName(DBField field) {
        ColumnMapping columnMapping = propertyMap.get(field);
        if (columnMapping != null) {
            return columnMapping.getRawColumnName();
        } else {
            throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + field + "'，或该属性被@Transient注释！");
        }
    }

    /**
     * 包装列名,便于别名替换
     * @param field
     * @return
     */
    public String wrapperColumnName(DBField field) {
        ColumnMapping columnMapping = propertyMap.get(field);
        if (columnMapping != null) {
            return SimpleSQLTemplate.wrapperColumn(columnMapping.getRawColumnName());
        } else {
            throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + field + "'，或该属性被@Transient注释！");
        }
    }

    /**
     * 指定要查询的属性列 - 这里会自动映射到表字段
     * @param properties
     * @return
     */
    public Example selectProperties(DBField... properties) {
        if (properties != null && properties.length > 0) {
            if (this.selectColumns == null) {
                this.selectColumns = new LinkedHashSet<>();
            }
            for (int i = 0; i < properties.length; i++) {
                DBField property = properties[i];
                if (propertyMap.containsKey(property)) {
                    this.selectColumns.add(property);
                } else {
                    throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
                }
            }
        }
        return this;
    }

    public Example selectProperties(Collection<DBField> properties) {
        if (properties != null && !properties.isEmpty()) {
            if (this.selectColumns == null) {
                this.selectColumns = new LinkedHashSet<>();
            }
            for (DBField property : properties) {
                if (propertyMap.containsKey(property)) {
                    this.selectColumns.add(property);
                } else {
                    throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
                }
            }
        }
        return this;
    }

    public Example selectDistinct(DBField... properties) {
        if (properties != null && properties.length > 0) {
            if (this.selectColumns == null) {
                this.selectColumns = new LinkedHashSet<>();
            }
            for (int i = 0; i < properties.length; i++) {
                DBField property = properties[i];
                if (propertyMap.containsKey(property)) {
                    this.selectColumns.add(property);
                } else {
                    throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
                }
            }
            this.distinct = true;
        }
        return this;
    }

    public Example selectDistinct(Collection<DBField> properties) {
        if (properties != null && !properties.isEmpty()) {
            if (this.selectColumns == null) {
                this.selectColumns = new LinkedHashSet<>();
            }
            for (DBField property : properties) {
                if (propertyMap.containsKey(property)) {
                    this.selectColumns.add(property);
                } else {
                    throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
                }
            }
            this.distinct = true;
        }
        return this;
    }

    public Example selectCount(DBField property) {
        if (propertyMap.containsKey(property)) {
            this.countColumn = property;
            this.count = true;
        } else {
            throw new SmallOrmException("类 " + entityClass.getSimpleName() + " 不包含属性 '" + property + "'，或该属性被@Transient注释！");
        }
        return this;
    }

    public Example selectCount() {
        this.count = true;
        return this;
    }

    public void or(Criteria criteria) {
        criteria.setAndOr("or");
        criterias.add(criteria);
    }

    public Criteria or() {
        Criteria criteria = createCriteriaInternal();
        criteria.setAndOr("or");
        criterias.add(criteria);
        return criteria;
    }

    public void and(Criteria criteria) {
        criteria.setAndOr("and");
        criterias.add(criteria);
    }

    public Criteria and() {
        Criteria criteria = createCriteriaInternal();
        criteria.setAndOr("and");
        criterias.add(criteria);
        return criteria;
    }

    public Criteria createCriteria() {
        Criteria criteria = createCriteriaInternal();
        if (criterias.size() == 0) {
            criteria.setAndOr("and");
            criterias.add(criteria);
        }
        return criteria;
    }

    protected Criteria createCriteriaInternal() {
        Criteria criteria = new Criteria(this, propertyMap, exists, notNull);
        return criteria;
    }

    public void clear() {
        criterias.clear();
        orderMap.clear();
        distinct = false;
    }

    protected abstract static class GeneratedCriteria {
        protected List<Criterion> criteria;
        //字段是否必须存在
        protected boolean exists;
        //值是否不能为空
        protected boolean notNull;
        //连接条件
        protected String andOr;
        //属性和列对应
        protected Map<DBField, ColumnMapping> propertyMap;
        protected Example example;

        protected GeneratedCriteria(Example example, Map<DBField, ColumnMapping> propertyMap, boolean exists, boolean notNull) {
            super();
            this.exists = exists;
            this.notNull = notNull;
            criteria = new ArrayList<Criterion>();
            this.propertyMap = propertyMap;
            this.example = example;
        }

        private ColumnMapping columnMapping(DBField property) {
            if (propertyMap.containsKey(property)) {
                return propertyMap.get(property);
            } else if (exists) {
                throw new SmallOrmException("当前实体类不包含名为" + property + "的属性!");
            } else {
                return null;
            }
        }

        private DBField property(DBField property) {
            if (propertyMap.containsKey(property)) {
                return property;
            } else if (exists) {
                throw new SmallOrmException("当前实体类不包含名为" + property + "的属性!");
            } else {
                return null;
            }
        }

        protected void addCriterion(String condition) {
            if (condition == null) {
                throw new SmallOrmException("Value for condition cannot be null");
            }
            if (condition.startsWith("null")) {
                return;
            }
            criteria.add(new Criterion(condition));
        }

        protected void addCriterion(String condition, DBField property) {
            if (property == null) {
                return;
            }
            criteria.add(new Criterion(condition, columnMapping(property)));
        }

        protected void addCriterion(String condition, Collection<?> values) {
            if (isNull(values, null)) {
                return;
            }
            if (values.isEmpty()) {
                criteria.add(new Criterion("1=1"));
                return;
            }
            criteria.add(new Criterion(condition, values));
        }

        protected void addCriterion(String condition, Object value, DBField property) {
            if (isNull(value, property)) {
                return;
            }
            if (property == null) {
                return;
            }
            criteria.add(new Criterion(condition, value, columnMapping(property)));
        }

        /**
         * @param condition
         * @param value
         * @param property
         * @param defaultValue 为空是否填充相等,true是,false为否
         */
        protected void addCriterionArray(String condition, Object value, DBField property, boolean defaultValue) {
            if (isNull(value, property)) {
                return;
            }
            Collection<?> values = null;
            if (value instanceof Collection) {
                values = (Collection<?>) value;
                if (values.isEmpty()) {
                    if (defaultValue) {
                        criteria.add(new Criterion("1=1"));
                    } else {
                        criteria.add(new Criterion("1=0"));
                    }
                    return;
                }
            } else if (value.getClass().isArray()) {
                int length = Array.getLength(value);
                if (length == 0) {
                    if (defaultValue) {
                        criteria.add(new Criterion("1=1"));
                    } else {
                        criteria.add(new Criterion("1=0"));
                    }
                    return;
                }
                values = CollectionUtils.arrayToList(value);
            } else {
                values = Collections.singletonList(value);
            }
            if (property == null) {
                return;
            }
            criteria.add(new Criterion(condition, values, columnMapping(property)));
        }

        private boolean isNull(Object value, DBField property) {
            if (value == null) {
                if (notNull) {
                    throw new SmallOrmException("Value for " + property + " cannot be null");
                } else {
                    criteria.add(new Criterion("1=1"));
                    return true;
                }
            }
            return false;
        }

        protected void addCriterion(String condition, Object value1, Object value2, DBField property) {
            if (value1 == null || value2 == null) {
                if (notNull) {
                    throw new SmallOrmException("Between values for " + property + " cannot be null");
                } else {
                    criteria.add(new Criterion("1=1"));
                    return;
                }
            }
            if (property == null) {
                return;
            }
            criteria.add(new Criterion(condition, Arrays.asList(value1, value2), columnMapping(property)));
        }

        public Criteria isNull(DBField property) {
            addCriterion(" is null", property(property));
            return (Criteria) this;
        }

        public Criteria isNotNull(DBField property) {
            addCriterion(" is not null", property(property));
            return (Criteria) this;
        }

        public Criteria eq(DBField property, Object value) {
            addCriterion(" =?", value, property(property));
            return (Criteria) this;
        }

        public Criteria ne(DBField property, Object value) {
            addCriterion(" <>?", value, property(property));
            return (Criteria) this;
        }

        public Criteria gt(DBField property, Object value) {
            addCriterion(" >?", value, property(property));
            return (Criteria) this;
        }

        public Criteria ge(DBField property, Object value) {
            addCriterion(" >= ?", value, property(property));
            return (Criteria) this;
        }

        public Criteria lt(DBField property, Object value) {
            addCriterion(" <?", value, property(property));
            return (Criteria) this;
        }

        public Criteria le(DBField property, Object value) {
            addCriterion(" <=? ", value, property(property));
            return (Criteria) this;
        }

        public Criteria in(DBField property, Collection<?> values) {
            // 对于空集合的IN条件为永假
            addCriterionArray(" in" + toIn(values), values, property(property), false);
            return (Criteria) this;
        }

        public Criteria in(DBField property, Object... values) {
            // 对于空集合的IN条件为永假
            addCriterionArray(" in" + toIn(values), values, property(property), false);
            return (Criteria) this;
        }

        protected String toIn(Object value) {
            StringBuilder sb = new StringBuilder();
            if (value instanceof Collection) {
                Collection<?> values = (Collection<?>) value;
                if (CollectionUtils.isNotEmpty(values)) {
                    sb.append("(");
                    for (int i = 0; i < values.size(); i++) {
                        sb.append(i > 0 ? "," : "").append("?");
                    }
                    sb.append(") ");
                }
            } else if (value.getClass().isArray()) {
                int length = Array.getLength(value);
                if (length > 0) {
                    sb.append("(");
                    for (int i = 0; i < length; i++) {
                        sb.append(i > 0 ? "," : "").append("?");
                    }
                    sb.append(")");
                }
            } else {
                sb.append("(?)");
            }
            return sb.toString();
        }

        public Criteria notIn(DBField property, Collection<?> values) {
            // 对于空集合的NOT IN条件为永真
            addCriterionArray(" not in" + toIn(values), values, property(property), true);
            return (Criteria) this;
        }

        public Criteria notIn(DBField property, Object... values) {
            // 对于空集合的NOT IN条件为永真
            addCriterionArray(" not in" + toIn(values), values, property(property), true);
            return (Criteria) this;
        }

        public Criteria between(DBField property, Object value1, Object value2) {
            addCriterion(" between ? and ? ", value1, value2, property(property));
            return (Criteria) this;
        }

        public Criteria notBetween(DBField property, Object value1, Object value2) {
            addCriterion(" not between ? and ?", value1, value2, property(property));
            return (Criteria) this;
        }

        public Criteria like(DBField property, String value) {
            addCriterion(" like ?", value, property(property));
            return (Criteria) this;
        }

        public Criteria like(DBField property, String value, char escape) {
            addCriterion(" like ? escape '" + escape + "'", value, property(property));
            return (Criteria) this;
        }

        public Criteria like(DBField property, String value, boolean escape) {
            addCriterion("  like ?" + (escape ? " escape '/'" : ""), value, property(property));
            return (Criteria) this;
        }

        public Criteria notLike(DBField property, String value) {
            addCriterion(" not like ?", value, property(property));
            return (Criteria) this;
        }

        public Criteria notLike(DBField property, String value, char escape) {
            addCriterion(" not like ? escape '" + escape + "'", value, property(property));
            return (Criteria) this;
        }

        public Criteria notLike(DBField property, String value, boolean escape) {
            addCriterion(" not like ?" + (escape ? " escape '/'" : ""), value, property(property));
            return (Criteria) this;
        }

        /**
         * 自定义条件
         * @param condition 例如 "length(countryname)<5"
         * @return
         */
        public Criteria addCondition(String condition) {
            addCriterion(condition);
            return (Criteria) this;
        }

        /**
         * 自定义左边条件，右边用value值
         * @param condition 例如 "length(countryname)="
         * @param value     例如 5
         * @return
         */
        public Criteria addCondition(String condition, DBField field, Object value) {
            criteria.add(new Criterion(condition, value, columnMapping(field)));
            return (Criteria) this;
        }

        /**
         * 自定义左边条件，右边用value值,支持? 参数,框架能自动替换,注意?和集合个数需要一一对应.
         * @param condition
         * @param values
         * @return
         */
        public Criteria addCondition(String condition, Collection<?> values) {
            addCriterion(condition, values);
            return (Criteria) this;
        }

        /**
         * or条件
         * @return
         */
        public Criteria or() {
            addCondition(" or ");
            return (Criteria) this;
        }

        /**
         * and条件
         * @return
         */
        public Criteria and() {
            addCondition(" and ");
            return (Criteria) this;
        }

        /**
         * 左括号
         * @return
         */
        public Criteria leftP() {
            addCondition("(");
            return (Criteria) this;
        }

        /**
         * 右括号
         * @return
         */
        public Criteria rightP() {
            addCondition(")");
            return (Criteria) this;
        }

        public List<Criterion> getAllCriteria() {
            return criteria;
        }

        public String getAndOr() {
            return andOr;
        }

        public void setAndOr(String andOr) {
            this.andOr = andOr;
        }

        public List<Criterion> getCriteria() {
            return criteria;
        }

        public boolean isValid() {
            return criteria.size() > 0;
        }

        public Example getExample() {
            return example;
        }
    }

    public static class Criteria extends GeneratedCriteria {

        public Criteria(Example example, Class<? extends DBObject> entityClass) {
            this(example, MetaHolder.getMeta(entityClass).getSchemaMap(), true, false);
        }

        protected Criteria(Example example, Map<DBField, ColumnMapping> propertyMap, boolean exists, boolean notNull) {
            super(example, propertyMap, exists, notNull);
        }
    }

    public enum ValueType {
        noValue, singleValue, arrayValue, listValue
    }

    public enum Order {
        ASC, DESC
    }

    public static class Criterion {
        /**
         * sql片段
         */
        private String condition;

        /**
         * 值,可为Collection子类或任意类型
         */
        private Object value;

        /**
         * 值类型
         */
        private ValueType valueType;
        /**
         * 字段列
         */
        private ColumnMapping column;

        protected Criterion(String condition) {
            this.condition = condition;
            this.valueType = ValueType.noValue;
        }

        protected Criterion(String condition, Collection<?> collection) {
            this.condition = condition;
            if (CollectionUtils.isNotEmpty(collection)) {
                value = collection;
                this.valueType = ValueType.listValue;
            } else {
                this.valueType = ValueType.noValue;
            }
        }

        protected Criterion(String condition, ColumnMapping column) {
            this.condition = condition;
            this.column = column;
            this.valueType = ValueType.noValue;
        }

        protected Criterion(String condition, Object value, ColumnMapping column) {
            this(condition, value, ValueType.singleValue, column);
        }

        protected Criterion(String condition, Collection<?> value, ColumnMapping column) {
            this(condition, value, ValueType.listValue, column);
        }

        protected Criterion(String condition, Object value, ValueType valueType, ColumnMapping column) {
            this.column = column;
            this.condition = condition;
            this.value = value;
            this.valueType = valueType;
        }

        public String getCondition() {
            return condition;
        }

        public ColumnMapping getColumn() {
            return column;
        }

        public Object getValue() {
            return value;
        }

        public ValueType getValueType() {
            return valueType;
        }
    }

    public static class OffsetLimit {

        private long offset;
        private int limit;

        public OffsetLimit(long offset, int limit) {
            this.offset = offset;
            this.limit = limit;
        }

        public long getOffset() {
            return offset;
        }

        public int getLimit() {
            return limit;
        }
    }

    public DBField getCountColumn() {
        return countColumn;
    }

    public String getDynamicTableName() {
        return tableName;
    }

    public Class<?> getEntityClass() {
        return entityClass;
    }

    public List<Criteria> getCriterias() {
        return criterias;
    }

    public Map<DBField, Order> getOrderMap() {
        return orderMap;
    }

    public List<DBField> getGroupByList() {
        return groupByList;
    }

    public Criterion getHaving() {
        return having;
    }

    public Set<DBField> getSelectColumns() {
        if (selectColumns != null && selectColumns.size() > 0) {
            //不需要处理
        } else if (excludeColumns != null && excludeColumns.size() > 0) {
            Collection<ColumnMapping> entityColumns = propertyMap.values();
            selectColumns = new LinkedHashSet<DBField>(entityColumns.size() - excludeColumns.size());
            for (ColumnMapping column : entityColumns) {
                if (!excludeColumns.contains(column.getColumn())) {
                    selectColumns.add(column.getField());
                }
            }
        }
        return selectColumns;
    }

    public boolean isDistinct() {
        return distinct;
    }

    public void setDistinct(boolean distinct) {
        this.distinct = distinct;
    }

    public boolean isForUpdate() {
        return forUpdate;
    }

    public void setForUpdate(boolean forUpdate) {
        this.forUpdate = forUpdate;
    }

    public boolean isUseBasicType() {
        return useBasicType;
    }

    public void setUseBasicType(boolean useBasicType) {
        this.useBasicType = useBasicType;
    }

    public boolean isWhereWrapper() {
        return whereWrapper;
    }

    public void setWhereWrapper(boolean whereWrapper) {
        this.whereWrapper = whereWrapper;
    }

    public boolean isCount() {
        return count;
    }

    public void setCount(boolean count) {
        this.count = count;
    }

    public OffsetLimit getOffsetLimit() {
        return offsetLimit;
    }

    public void setOffsetLimit(OffsetLimit offsetLimit) {
        this.offsetLimit = offsetLimit;
    }

    /**
     * 设置字段的表别名
     * @param name
     * @param useAlias
     * @return
     */
    public String getColumnAlias(String name, boolean useAlias) {
        if (useAlias && StringUtils.isNotBlank(alias)) {
            return alias + "." + name;
        }
        return name;
    }

    public String getTableNameAlias(String name, boolean useAlias) {
        if (useAlias && StringUtils.isNotBlank(alias)) {
            return name + " " + alias;
        }
        return name;
    }

    public void setDialect(DBDialect dialect) {
        this.dialect = dialect;
    }
}